#!/usr/bin/env python
import os
import sys
import pwd
import grp as gwd

# Django imports
import settings
from django.core.management.base import BaseCommand, CommandError

CONV = {
    '0': '---', '1': '--x', '2': '-w-', '3': '-wx',
    '4': 'r--', '5': 'r-x', '6': 'rw-', '7': 'rwx'
}
MODS = {
    '0': {},
    '1': {'o': (lambda o: '%st' % o[:2] if o[-1] == 'x' else '%sT' % o[:2])},
    '2': {'g': (lambda g: '%ss' % g[:2] if g[-1] == 'x' else '%sS' % g[:2])},
    '4': {'u': (lambda u: '%ss' % u[:2] if u[-1] == 'x' else '%sS' % u[:2])},
    '3': ['1', '2'],
    '5': ['1', '4'],
    '6': ['2', '4'],
    '7': ['1', '2', '4']
}

def unix_bit(octl): 
    # Break the octal set into parts
    otl = oct(octl)[1:]
    mod = '0' if len(otl) == 3 else otl[0]
    usr, grp, oth = otl if len(otl) == 3 else otl[1:]

    # Convert and handle special bits
    usr, grp, oth = CONV[usr], CONV[grp], CONV[oth] 
    mod = MODS[mod] if isinstance(MODS[mod], list) else [mod]
    for m in mod:
        if 'u' in MODS[m]: usr = MODS[m]['u'](usr)
        if 'g' in MODS[m]: grp = MODS[m]['g'](grp)
        if 'o' in MODS[m]: oth = MODS[m]['o'](oth)

    # Return the resulting bit string
    return '%s%s%s' % (usr, grp, oth)

def fix_perm(dmod, fmod, user, group, spec = {}):
    # Step through the project root fixing permissions
    for root, dirs, files in os.walk(os.getcwd()):
        items = [''] + dirs + files
        for i in items:
            # Get the path of the item
            path = os.path.join(root, i)

            # Set the correct permissions with overrides
            mod = dmod if os.path.isdir(path) else fmod
            usr, grp = user, group
            if i in spec:
                opts = spec[i]
                mod = opts[0] if opts[0] is not None else mod
                usr = opts[1] if opts[1] is not None else usr
                grp = opts[2] if opts[2] is not None else grp

            # Convert the user and group into ids
            try:
                usrd = pwd.getpwnam(usr)[2]
            except: raise Exception('Invalid user: \'%s\'' % usr)
            try:
                grpd = gwd.getgrnam(grp)[2]
            except: raise Exception('Invalid group: \'%s\'' % grp)

            # Change the permissions
            os.chmod(path, mod)
            os.chown(path, usrd, grpd)
            print '%s%s\t%s %s\t%s' % (
                'd' if os.path.isdir(path) else '-', 
                unix_bit(mod), usr, grp,
                i if len(i) != 0 else os.path.basename(root.strip('./')), 
            )

class Command(BaseCommand):
    args = ''
    help = 'Fixes the file system permissions of the project'

    def handle(self, *args, **options):
        try:
            fix_perm(
                settings.DMOD, settings.FMOD, 
                settings.USR, settings.GRP,
                settings.SPEC
            )
        except Exception, e:
            raise CommandError(str(e))
